package org.paradac;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

public class DCThreadPoolExecutor {

	private int corePoolSize;
	private int maximumPoolSize;

	private List<WorkerThread> workingThreads = new ArrayList<WorkerThread>();

	public DCThreadPoolExecutor(int corePoolSize, int maximumPoolSize) {
		super();
		this.corePoolSize = corePoolSize;
		this.maximumPoolSize = maximumPoolSize;
		for (int i = 0; i < this.corePoolSize; i++) {
			workingThreads.add(new WorkerThread());
		}
	}

	private AtomicInteger count = new AtomicInteger(0);

	public void execute(Runnable command) {
		count.incrementAndGet();
		workQueue.offer(command);
	}

	public void executeAll(List<Runnable> a) {
		for (int i = 0; i < a.size(); i++) {
			execute(a.get(i));
		}
	}

	public void run() {
		for (int i = 0; i < this.corePoolSize; i++) {
			workingThreads.get(i).start();
		}
		while (!(count.get() == 0)) {
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		for (int i = 0; i < workingThreads.size(); i++) {
			workingThreads.get(i).setQuit();
		}
	}

	private Queue<Runnable> workQueue = new ConcurrentLinkedQueue<Runnable>();

	private class WorkerThread
	    extends Thread {

		boolean quit = false;
		@Override
		public void run() {
			while (!quit) {
				Runnable work = workQueue.poll();
				if (work != null) {
					work.run();
					DCThreadPoolExecutor.this.count.decrementAndGet();
				} else {
					try {
						Thread.sleep(0);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}

		public void setQuit() {
			quit = true;
		}
	}
}
